5450 #include "types.h"
5451 #include "defs.h"
5452 #include "param.h"
5453 #include "mmu.h"
5454 #include "proc.h"
5455 #include "fs.h"
5456 #include "file.h"
5457 #include "spinlock.h"
5458 
5459 #define PIPESIZE 512
5460 
5461 struct pipe {
5462   struct spinlock lock;
5463   char data[PIPESIZE];
5464   uint nread;     // number of bytes read
5465   uint nwrite;    // number of bytes written
5466   int readopen;   // read fd is still open
5467   int writeopen;  // write fd is still open
5468 };
5469 
5470 int
5471 pipealloc(struct file **f0, struct file **f1)
5472 {
5473   struct pipe *p;
5474 
5475   p = 0;
5476   *f0 = *f1 = 0;
5477   if((*f0 = filealloc()) == 0 || (*f1 = filealloc()) == 0)
5478     goto bad;
5479   if((p = (struct pipe*)kalloc()) == 0)
5480     goto bad;
5481   p->readopen = 1;
5482   p->writeopen = 1;
5483   p->nwrite = 0;
5484   p->nread = 0;
5485   initlock(&p->lock, "pipe");
5486   (*f0)->type = FD_PIPE;
5487   (*f0)->readable = 1;
5488   (*f0)->writable = 0;
5489   (*f0)->pipe = p;
5490   (*f1)->type = FD_PIPE;
5491   (*f1)->readable = 0;
5492   (*f1)->writable = 1;
5493   (*f1)->pipe = p;
5494   return 0;
5495 
5496 
5497 
5498 
5499 
5500  bad:
5501   if(p)
5502     kfree((char*)p);
5503   if(*f0)
5504     fileclose(*f0);
5505   if(*f1)
5506     fileclose(*f1);
5507   return -1;
5508 }
5509 
5510 void
5511 pipeclose(struct pipe *p, int writable)
5512 {
5513   acquire(&p->lock);
5514   if(writable){
5515     p->writeopen = 0;
5516     wakeup(&p->nread);
5517   } else {
5518     p->readopen = 0;
5519     wakeup(&p->nwrite);
5520   }
5521   if(p->readopen == 0 && p->writeopen == 0) {
5522     release(&p->lock);
5523     kfree((char*)p);
5524   } else
5525     release(&p->lock);
5526 }
5527 
5528 int
5529 pipewrite(struct pipe *p, char *addr, int n)
5530 {
5531   int i;
5532 
5533   acquire(&p->lock);
5534   for(i = 0; i < n; i++){
5535     while(p->nwrite == p->nread + PIPESIZE) {  //DOC: pipewrite-full
5536       if(p->readopen == 0 || proc->killed){
5537         release(&p->lock);
5538         return -1;
5539       }
5540       wakeup(&p->nread);
5541       sleep(&p->nwrite, &p->lock);  //DOC: pipewrite-sleep
5542     }
5543     p->data[p->nwrite++ % PIPESIZE] = addr[i];
5544   }
5545   wakeup(&p->nread);  //DOC: pipewrite-wakeup1
5546   release(&p->lock);
5547   return n;
5548 }
5549 
5550 int
5551 piperead(struct pipe *p, char *addr, int n)
5552 {
5553   int i;
5554 
5555   acquire(&p->lock);
5556   while(p->nread == p->nwrite && p->writeopen){  //DOC: pipe-empty
5557     if(proc->killed){
5558       release(&p->lock);
5559       return -1;
5560     }
5561     sleep(&p->nread, &p->lock); //DOC: piperead-sleep
5562   }
5563   for(i = 0; i < n; i++){  //DOC: piperead-copy
5564     if(p->nread == p->nwrite)
5565       break;
5566     addr[i] = p->data[p->nread++ % PIPESIZE];
5567   }
5568   wakeup(&p->nwrite);  //DOC: piperead-wakeup
5569   release(&p->lock);
5570   return i;
5571 }
5572 
5573 
5574 
5575 
5576 
5577 
5578 
5579 
5580 
5581 
5582 
5583 
5584 
5585 
5586 
5587 
5588 
5589 
5590 
5591 
5592 
5593 
5594 
5595 
5596 
5597 
5598 
5599 
